package com.ww.exercise.coroutine.hard.q23

import kotlinx.coroutines.*
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import kotlin.system.measureTimeMillis

// 任务结果数据类
data class TaskResult(
    val taskId: String,
    val processingType: String, // "coroutine" 或 "thread"
    val durationMs: Long,
    val success: Boolean = true
)

// 模拟业务任务
class BusinessTask(
    val id: String,
    val type: String, // 用于区分任务类型，如"critical"核心任务
    val processingTimeMs: Long // 模拟处理时间
)

class HybridProcessingSystem {
    // 1. 创建现有线程池
    private val coreThreadPool = Executors.newFixedThreadPool(100)
    // 2. 将线程池转换为协程调度器
    private val threadPoolDispatcher = coreThreadPool.asCoroutineDispatcher()

    // 平滑过渡控制器 - 控制协程处理任务的比例
    @Volatile
    private var coroutineProcessingRatio = 0.0 // 0.0-1.0

    // 设置协程处理比例，用于平滑过渡
    fun setCoroutineRatio(ratio: Double) {
        coroutineProcessingRatio = ratio.coerceIn(0.0, 1.0)
    }

    // 处理任务入口 - 自动选择处理方式
    suspend fun processTasks(tasks: List<BusinessTask>): List<TaskResult> {
        return withContext(Dispatchers.Default) {
            tasks.map { task ->
                async {
                    if (shouldUseCoroutine(task)) {
                        processWithCoroutine(task)
                    } else {
                        processWithThreadPool(task)
                    }
                }
            }.awaitAll()
        }
    }

    // 决定是否使用协程处理
    private fun shouldUseCoroutine(task: BusinessTask): Boolean {
        // 核心任务始终使用线程池，确保稳定性
        if (task.type == "critical") {
            return false
        }
        // 根据比例决定处理方式
        return Math.random() < coroutineProcessingRatio
    }

    // 使用协程处理任务（基于线程池调度器）
    private suspend fun processWithCoroutine(task: BusinessTask): TaskResult {
        return withContext(threadPoolDispatcher) {
            val startTime = System.currentTimeMillis() // 记录开始时间，用于计算总耗时
            return@withContext try {
                // 使用withTimeout而非withTimeoutOrNull，让框架自动抛出超时异常
                withTimeout(task.processingTimeMs) {
                    delay(task.processingTimeMs) // 模拟IO操作（可取消）
                    // 任务成功完成
                    TaskResult(
                        taskId = task.id,
                        processingType = "coroutine",
                        durationMs = System.currentTimeMillis() - startTime,
                        success = true
                    )
                }
            } catch (e: TimeoutCancellationException) {
                // 捕获框架自动抛出的超时异常（无需手动创建）
                TaskResult(
                    taskId = task.id,
                    processingType = "coroutine",
                    durationMs = System.currentTimeMillis() - startTime,
                    success = false,
                )
            } catch (e: Exception) {
                // 处理其他异常（如业务异常、取消异常等）
                TaskResult(
                    taskId = task.id,
                    processingType = "coroutine",
                    durationMs = System.currentTimeMillis() - startTime,
                    success = false,
                )
            }
        }
    }

    // 使用原生线程池处理任务
    private fun processWithThreadPool(task: BusinessTask): TaskResult {
        // 记录任务开始时间（用于计算总耗时，替代嵌套的measureTimeMillis）
        val startTime = System.currentTimeMillis()

        val future = coreThreadPool.submit {
            try {
                Thread.sleep(task.processingTimeMs) // 模拟阻塞IO
            } catch (e: InterruptedException) {
                Thread.currentThread().interrupt() // 保留中断状态
                throw e
            }
        }

        return try {
            // 计算获取结果的耗时（包含在总耗时内）
            val getDuration = measureTimeMillis {
                future.get(task.processingTimeMs + 1000, TimeUnit.MILLISECONDS)
            }
            // 总耗时 = 从任务开始到获取结果的时间
            TaskResult(
                taskId = task.id,
                processingType = "thread",
                durationMs = System.currentTimeMillis() - startTime,
                success = true
            )
        } catch (e: Exception) {
            future.cancel(true)
            // 异常情况下的总耗时 = 从任务开始到异常发生的时间
            TaskResult(
                taskId = task.id,
                processingType = "thread",
                durationMs = System.currentTimeMillis() - startTime,
                success = false,
            )
        }
    }

    // 资源清理
    fun shutdown() {
        threadPoolDispatcher.close()
        coreThreadPool.shutdown()
        if (!coreThreadPool.awaitTermination(5, TimeUnit.SECONDS)) {
            coreThreadPool.shutdownNow()
        }
    }
}

// 性能测试函数
suspend fun runPerformanceTest(
    system: HybridProcessingSystem,
    ratio: Double,
    taskCount: Int = 500
) {
    system.setCoroutineRatio(ratio)

    // 生成测试任务：80%普通任务，20%核心任务
    val tasks = (1..taskCount).map {
        val isCritical = it % 5 == 0 // 20%核心任务
        BusinessTask(
            id = "task-$it",
            type = if (isCritical) "critical" else "normal",
            processingTimeMs = (100 + Math.random() * 1000).toLong() // 100-1100ms随机处理时间
        )
    }

    println("\n=== 测试：协程处理比例 ${ratio*100}% ===")
    val totalTime = measureTimeMillis {
        val results = system.processTasks(tasks)

        val coroutineResults = results.filter { it.processingType == "coroutine" }
        val threadResults = results.filter { it.processingType == "thread" }

        println("总任务数: ${results.size}")
        println("协程处理: ${coroutineResults.size} (成功率: ${coroutineResults.count { it.success } * 100.0 / coroutineResults.size}%)")
        println("线程处理: ${threadResults.size} (成功率: ${threadResults.count { it.success } * 100.0 / threadResults.size}%)")
        println("平均处理时间 - 协程: ${coroutineResults.map { it.durationMs }.average().toLong()}ms")
        println("平均处理时间 - 线程: ${threadResults.map { it.durationMs }.average().toLong()}ms")
    }

    println("总耗时: $totalTime ms")
}

fun main() = runBlocking {
    val hybridSystem = HybridProcessingSystem()

    try {
        // 平滑过渡策略：从0%协程逐步过渡到100%
        runPerformanceTest(hybridSystem, 0.0)   // 全线程池
        runPerformanceTest(hybridSystem, 0.2)   // 20%协程
        runPerformanceTest(hybridSystem, 0.5)   // 50%协程
        runPerformanceTest(hybridSystem, 0.8)   // 80%协程
        runPerformanceTest(hybridSystem, 1.0)   // 全协程
    } finally {
        hybridSystem.shutdown()
    }

    println("\n=== 平滑过渡策略总结 ===")
    println("1. 初期(0-20%)：验证协程基础功能，只迁移非核心任务")
    println("2. 中期(30-50%)：扩大协程应用范围，监控性能指标")
    println("3. 后期(60-80%)：重点测试高负载下表现，解决潜在问题")
    println("4. 完成(100%)：全量迁移，退役原生线程池代码")
}